// 扩展。支持以时间为单位、滚动文件的落地方式

#include "../logsystem/snowdragon.h"

// 滚动文件以时间为单位，落地测试

enum class TimeGap
{
    SECOND,
    MIN,
    HOUSE,
    DAY
};

class RollFileByTimeSink : public snowdragon::Sink
{
public:
    using ptr = std::shared_ptr<RollFileByTimeSink>;
    RollFileByTimeSink(const std::string &base_file_path_name, TimeGap time_gap)
        : _base_file_path_name(base_file_path_name)
    {
        snowdragon::util::File::createDirectory(snowdragon::util::File::getPath(_base_file_path_name));
        createFile();
        switch (time_gap)
        {
        case TimeGap::SECOND:
            _time_gap = 1;
            break;
        case TimeGap::MIN:
            _time_gap = 60;
            break;
        case TimeGap::HOUSE:
            _time_gap = 3600;
            break;
        case TimeGap::DAY:
            _time_gap = 3600 * 24;
            break;
        }
        _file_time_gap = snowdragon::util::Date::nowDate();
    }
    void log(const char *str, size_t len)
    {
        if (_file_time_gap + _time_gap < snowdragon::util::Date::nowDate())
            createFile();
        _ofs.write(str, len);
        assert(_ofs.good());
        // _file_time_gap = snowdragon::util::Date::nowDate() % _time_gap;
    }

private:
    void createFile()
    {
        _ofs.close();
        _ofs.open(getNewFileName(), std::ios::binary | std::ios::trunc);
        assert(_ofs.is_open());
        _file_time_gap = snowdragon::util::Date::nowDate(); // 记得修改，方便下次操作，否则将一直创建文件
    }
    std::string getNewFileName() // 封装，更美观些
    {
        std::stringstream ss;
        ss << _base_file_path_name;
        struct tm t;
        time_t now_time = snowdragon::util::Date::nowDate();
        localtime_r(&now_time, &t);
        ss << t.tm_year + 1900;
        ss << t.tm_mon + 1;
        ss << t.tm_mday;
        ss << t.tm_hour;
        ss << t.tm_min;
        ss << t.tm_sec;
        ss << "-";                  // 美观
        ss << _file_count++;
        ss << ".log";
        return ss.str();
    }

private:
    std::string _base_file_path_name; // 基本文件名
    std::ofstream _ofs;               // 方便操作，不会多次重复关闭与打开
    int _time_gap;                    // 时间间隙
    time_t _file_time_gap;            // 当前文件时间间隙
    int _file_count = 0;              // 文件计数器。防止在一秒内多次创建文件，而文件名相同导致创建失败的情况
};

// 直接构造消息进行测试
void usage1()
{
    std::shared_ptr<snowdragon::Formatter> fmt(new snowdragon::Formatter("ab%%cd[%d{%H:%M:%S}][%t][%c][%p][%f:%l]%T%m%n"));
    snowdragon::Message msg("test.cc", 66, snowdragon::LogLevel::Level::INFO, "测试format.hpp", "root");
    std::string str = fmt->format(msg);
    snowdragon::Sink::ptr rfbtp = snowdragon::SinkFactory::createSink<RollFileByTimeSink>("./logfiles/rollFileSink-", TimeGap::SECOND);

    rfbtp->log(str.c_str(), str.size());
    int size = 0;
    int count = 0;
    while (size < 1024 * 1024 * 6)
    {
        std::string tmp = str + std::to_string(count++);
        rfbtp->log(tmp.c_str(), tmp.size());
        size += tmp.size();
        usleep(10); // 略停，运行后，约2秒，创建一个文件，滚动
    }
}

// 使用示例
void usage2()
{
    snowdragon::GlobalLoggerBuilder::ptr glb(new snowdragon::GlobalLoggerBuilder);
    glb->buildLoggerName("asynchronous");
    glb->buildLoggerType(snowdragon::Logger::LoggerType::ASYNC_LOGGER);
    glb->buildLoggerSink<RollFileByTimeSink>("./logfiles/rollFileSink-", TimeGap::SECOND);
    snowdragon::Logger::ptr logger = glb->build();
    snowdragon::LoggerManager::getInstance().pushLogger(logger);
    for (int i = 0; i < 30000; ++i)
    {
        logger->fatal("expandUsage测试 %d", i);
        usleep(10);             // 略停，运行后，约2秒，创建一个文件，滚动
    }
}

int main()
{
    // usage1();
    usage2();

    return 0;
}